﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace SharpSoft.WPF.Controls
{
    public class MultiMediaBrowserEx : MultiMediaBrowser
    {
        static MultiMediaBrowserEx()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiMediaBrowserEx), new FrameworkPropertyMetadata(typeof(MultiMediaBrowserEx)));
        }

        public MultiMediaBrowserEx()
        {
            this.CircleVisit = true;
        }

        protected MultiMediaControl media_pre, media_next;
        public override void OnApplyTemplate()
        {
            this.media_pre = (MultiMediaControl)this.GetTemplateChild("media_pre");
            this.media_next = (MultiMediaControl)this.GetTemplateChild("media_next");
            base.OnApplyTemplate();
            media.RenderTransformOrigin = media_pre.RenderTransformOrigin = media_next.RenderTransformOrigin = new Point(0.5, 0.5);
            TransformGroup tg = new TransformGroup();
            tg.Children.Add(new ScaleTransform(1, 1));
            tg.Children.Add(new TranslateTransform(0, 0));
            media.RenderTransform = tg;
            tg = new TransformGroup();
            tg.Children.Add(new ScaleTransform(this.AssistScale, this.AssistScale));
            tg.Children.Add(new TranslateTransform(0, 0));
            media_pre.RenderTransform = tg;
            tg = new TransformGroup();
            tg.Children.Add(new ScaleTransform(this.AssistScale, this.AssistScale));
            tg.Children.Add(new TranslateTransform(0, 0));
            media_next.RenderTransform = tg;
            layout();
            OnProgress();
        }

        protected override void OnApplyingMedia()
        {
            base.OnApplyingMedia();
            if (media_pre != null && media_next != null)
            {

                media_pre.Source = getSource(CurrentIndex - 1);
                media_next.Source = getSource(CurrentIndex + 1);

            }
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == AssistDistanceProperty || e.Property == PrimarySizeProperty || e.Property == AssistScaleProperty)
            {
                layout();
            }
            else if (e.Property == ProgressProperty)
            {
                OnProgress();
            }
        }

        /// <summary>
        /// 辅助对象的缩放
        /// </summary>
        public double AssistScale
        {
            get { return (double)GetValue(AssistScaleProperty); }
            set { SetValue(AssistScaleProperty, value); }
        }

        public static readonly DependencyProperty AssistScaleProperty =
            DependencyProperty.Register("AssistScale", typeof(double), typeof(MultiMediaBrowserEx), new PropertyMetadata(0.8d));

        /// <summary>
        /// 辅助对象的中心与主媒体对象中心的距离
        /// </summary>
        public double AssistDistance
        {
            get { return (double)GetValue(AssistDistanceProperty); }
            set { SetValue(AssistDistanceProperty, value); }
        }

        public static readonly DependencyProperty AssistDistanceProperty =
            DependencyProperty.Register("AssistDistance", typeof(double), typeof(MultiMediaBrowserEx), new PropertyMetadata(1d));



        /// <summary>
        /// 主媒体的尺寸（百分比）
        /// </summary>
        public Size PrimarySize
        {
            get { return (Size)GetValue(PrimarySizeProperty); }
            set { SetValue(PrimarySizeProperty, value); }
        }

        public static readonly DependencyProperty PrimarySizeProperty =
            DependencyProperty.Register("PrimarySize", typeof(Size), typeof(MultiMediaBrowserEx), new PropertyMetadata(new Size(0.8, 1)));

        /// <summary>
        /// 动画进度
        /// </summary>
        public double Progress
        {
            get { return (double)GetValue(ProgressProperty); }
            set { SetValue(ProgressProperty, value); }
        }

        public static readonly DependencyProperty ProgressProperty =
            DependencyProperty.Register("Progress", typeof(double), typeof(MultiMediaBrowserEx), new PropertyMetadata(0d));



        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);
            this.layout();
        }

        private void layout()
        {
            if (media != null)
            {
                media.Width = this.RenderSize.Width * PrimarySize.Width;
                media.Height = this.RenderSize.Height * PrimarySize.Height;
                Canvas.SetLeft(media, (this.RenderSize.Width - media.Width) / 2d);
                Canvas.SetTop(media, (this.RenderSize.Height - media.Height) / 2d);
            }
            if (media_pre != null)
            {
                media_pre.Width = media.Width;
                media_pre.Height = media.Height;
                Canvas.SetLeft(media_pre, Canvas.GetLeft(media) - media.Width * AssistDistance);
                Canvas.SetTop(media_pre, Canvas.GetTop(media));
            }
            if (media_next != null)
            {
                media_next.Width = media.Width;
                media_next.Height = media.Height;
                Canvas.SetLeft(media_next, Canvas.GetLeft(media) + media.Width * AssistDistance);
                Canvas.SetTop(media_next, Canvas.GetTop(media));
            }
            OnProgress();
        }


        private void OnProgress()
        {
            var p = this.Progress;
            double pf;
            if (p != 1d)
            {
                pf = p - (int)p;
            }
            else
            {
                pf = p;
            }
            if (media != null)
            {
                var tt = (TranslateTransform)((TransformGroup)media.RenderTransform).Children[1];
                var st = (ScaleTransform)((TransformGroup)media.RenderTransform).Children[0];

                st.ScaleX = st.ScaleY = 1 - (1 - AssistScale) * Math.Abs(pf);


                tt.X = -media.Width * AssistDistance * p;
            }
            if (media_pre != null)
            {
                var tt = (TranslateTransform)((TransformGroup)media_pre.RenderTransform).Children[1];
                var st = (ScaleTransform)((TransformGroup)media_pre.RenderTransform).Children[0];

                if (p >= 0.5)
                {//移动超过一半，pre元素紧跟next
                    tt.X = Canvas.GetLeft(media_next) - Canvas.GetLeft(media_pre) + media_pre.Width - media_next.Width * AssistDistance * p;
                    st.ScaleX = st.ScaleY = AssistScale - (1 - AssistScale) * (1 - pf);
                    media_pre.Source = getSource(CurrentIndex + 2);
                }
                else
                {
                    tt.X = -media_pre.Width * AssistDistance * p;
                    st.ScaleX = st.ScaleY = AssistScale - (1 - AssistScale) * pf;
                    media_pre.Source = getSource(CurrentIndex - 1);
                } 
            }
            if (media_next != null)
            {
                var tt = (TranslateTransform)((TransformGroup)media_next.RenderTransform).Children[1];
                var st = (ScaleTransform)((TransformGroup)media_next.RenderTransform).Children[0];
                if (p <= -0.5)
                {//移动超过一半，next元素紧跟pre
                    tt.X = (Canvas.GetLeft(media_pre) - Canvas.GetLeft(media_next)) + media_next.Width * AssistDistance * (-1 - p);
                    st.ScaleX = st.ScaleY = AssistScale * pf * (-1);

                    media_next.Source = getSource(CurrentIndex - 2);
                }
                else
                {
                    tt.X = -media_next.Width * AssistDistance * p;
                    st.ScaleX = st.ScaleY = AssistScale + (1 - AssistScale) * pf;
                    media_next.Source = getSource(CurrentIndex + 1);
                }

            }
        }


        #region 动画

        /// <summary>
        /// 动画到下一媒体
        /// </summary>
        /// <param name="dur"></param>
        public void Next(TimeSpan dur)
        {
            Next((da) => { da.Duration = dur; });
        }
        /// <summary>
        /// 动画到下一媒体
        /// </summary>
        /// <param name="func"></param>
        public void Next(Action<DoubleAnimation> func)
        {
            DoubleAnimation da = new DoubleAnimation() { From = 0, To = 1, FillBehavior = FillBehavior.Stop };
            func?.Invoke(da);
            da.Completed += (s, e) =>
            {
                this.Progress = 0;
                this.Goto(CurrentIndex + 1);
            };
            this.BeginAnimation(ProgressProperty, da);
        }


        /// <summary>
        /// 动画到上一媒体
        /// </summary>
        /// <param name="dur"></param>
        public void Previous(TimeSpan dur)
        {
            Previous((da) => { da.Duration = dur; });
        }
        /// <summary>
        /// 动画到上一媒体
        /// </summary>
        /// <param name="func"></param>
        public void Previous(Action<DoubleAnimation> func)
        {
            DoubleAnimation da = new DoubleAnimation() { From = 0, To = -1, FillBehavior = FillBehavior.Stop };
            func?.Invoke(da);
            da.Completed += (s, e) =>
            {
                this.Progress = 0;
                this.Goto(CurrentIndex - 1);
            };
            this.BeginAnimation(ProgressProperty, da);
        }
        ///// <summary>
        ///// 动画转到指定的索引
        ///// </summary>
        ///// <param name="index"></param>
        ///// <param name="dur"></param>
        //public void Goto(int index, TimeSpan dur)
        //{
        //    Goto(index, (da) => { da.Duration = dur; });
        //}
        ///// <summary>
        ///// 动画转到指定的索引
        ///// </summary>
        ///// <param name="index"></param>
        ///// <param name="func"></param>
        //public void Goto(int index, Action<DoubleAnimation> func)
        //{
        //    DoubleAnimation da = new DoubleAnimation() { From = 0, To = index - CurrentIndex, FillBehavior = FillBehavior.Stop };
        //    func?.Invoke(da);
        //    da.Completed += (s, e) =>
        //    {
        //        this.Progress = 0;
        //        this.Goto(index);
        //    };
        //    this.BeginAnimation(ProgressProperty, da);
        //}
        #endregion

    }
}
